package symbol;

import java.util.ArrayList;
import java.util.HashMap;

import ast.AstItem;
import ast.ComplexDataSignature;
import ast.PrimaryDataSignature;

public class astPreprocessContext {
	// 记录定义的各个函数的重载情况
	// 类方法：<ClassName>.<Funckey>
	// 类构造器：<ClassName>.constructor.<FunckeyPfix>
	// 普通方法：<Funckey>
	private HashMap<String, ArrayList<FuncParamsTypeList>> funcReload = new HashMap<String, ArrayList<FuncParamsTypeList>>();
	// 记录每个域（函数）的func变量的使用情况
	private HashMap<String, FuncVariableTable> funcTables = new HashMap<String, FuncVariableTable>();
	// 记录每个域（函数）的类型情况
	private HashMap<String, SymbolTable> symbolTables = new HashMap<String, SymbolTable>();
	// 全局函数变量记录表
	private FuncVariableTable globalFuncTables = new FuncVariableTable();
	// 全局符号表
	private SymbolTable globalSymbolTables = new SymbolTable();
	// 记录当前的函数名字（包括普通函数、类方法、类构造器，不含类的前缀）
	public String nowFuncKey;
	// 记录当前类的名字
	public String nowClassField;
	// 记录所有的类名
	public ArrayList<String> classList = new ArrayList<String>();
	// 记录函数的类型（func<xxx>）
	public HashMap<String, String> funcTypeMap = new HashMap<String, String>();
	// 记录类的初始化
	public HashMap<String, ArrayList<AstItem>> class2attrAssign = new HashMap<String, ArrayList<AstItem>>();
	
	private astPreprocessContext() {}
    private static astPreprocessContext globalContext = null; 
    public static astPreprocessContext getContext() {
         if (globalContext == null) {  
        	 globalContext = new astPreprocessContext();
         }  
        return globalContext;
    }
    
    public static void addFuncReload(String funcName, FuncParamsTypeList funcType) {
    	if (globalContext.funcReload.containsKey(funcName)) {
    		globalContext.funcReload.get(funcName).add(funcType);
    	} else {
    		globalContext.funcReload.put(funcName, new ArrayList<FuncParamsTypeList>());
    		globalContext.funcReload.get(funcName).add(funcType);
    	}
    }
    
    public static void createFuncTables(String funcName, FuncParamsTypeList funcType) {
    	// 新建函数变量表
    	String funcKey = "_" + funcName + "_" + funcType.toString();
    	globalContext.nowFuncKey = funcKey;
    	globalContext.funcTables.put(funcKey, new FuncVariableTable());
    }
    
    public static void createSymbolTables(String funcName, FuncParamsTypeList funcType, ArrayList<String> paramsName) {
    	// 记录函数的类型（func<xxx>）格式
    	globalContext.funcTypeMap.put(funcName, "func<" + funcType.returnType + ">");
    	// 新建符号表，并把形参填进符号表
    	String funcKey = "_" + funcName + "_" + funcType.toString();
    	globalContext.nowFuncKey = funcKey;
    	globalContext.symbolTables.put(funcKey, new SymbolTable());
    	assert paramsName.size() == funcType.typeList.size();
    	for (int i = 0;i < paramsName.size();i++) {
        	globalContext.symbolTables.get(funcKey).tableInfo.put(
        			paramsName.get(i), new SymbolTableItem(paramsName.get(i), funcType.typeList.get(i)));
    	}
    }
    
    public static void removeNowFuncKey() {
    	globalContext.nowFuncKey = null;
    }
    
    public static void removeNowClass() {
    	globalContext.nowClassField = null;
    }
    
    public static void updateNowFunckey(String funckey) {
    	globalContext.nowFuncKey = funckey;
    }
    
    public static void updateNowClass(String classname) {
    	globalContext.nowClassField = classname;
    }
    
    public static FuncVariableTable getNowFuncTable() {
    	FuncVariableTable table = globalContext.funcTables.get(globalContext.nowFuncKey);
    	if (table == null) return globalContext.globalFuncTables;
    	else return table;
    }
    
    public static void addFuncvarInfo(String funcVarkey, ArrayList<String> params, String returnType) {
    	getNowFuncTable().addFuncvarInfo(funcVarkey, params, returnType);
    }
    
    public static SymbolTable getNowSymbolTables() {
    	SymbolTable table = globalContext.symbolTables.get(globalContext.nowFuncKey);
    	if (table == null) return globalContext.globalSymbolTables;
    	else return table;
    }
    
    public static String getNowFunckey() {
    	return globalContext.nowFuncKey;
    }
    
    public static String getNowClass() {
    	return globalContext.nowClassField;
    }

    public static void class_addSymbolInfo(PrimaryDataSignature declVar, String classname) {
    	// 填入符号表
    	assert declVar.dataType != null;
    	astPreprocessContext.getContext();
    	astPreprocessContext.getNowSymbolTables().class_addSymbolInfo(declVar, classname);
    }
    
    public static void class_addSymbolInfo_array(ComplexDataSignature declVar, String classname) {
    	// 填入符号表
    	assert declVar.dataType != null;
    	astPreprocessContext.getContext();
    	astPreprocessContext.getNowSymbolTables().class_addSymbolInfo_array(declVar, classname);
    }
    
    public static void addSymbolInfo(PrimaryDataSignature declVar) {
    	// 填入符号表
    	assert declVar.dataType != null;
    	astPreprocessContext.getContext();
    	astPreprocessContext.getNowSymbolTables().addSymbolInfo(declVar);
    }
    
    public static void addSymbolInfo_array(ComplexDataSignature declVar) {
    	// 填入符号表
    	assert declVar.dataType != null;
    	astPreprocessContext.getContext();
    	astPreprocessContext.getNowSymbolTables().addSymbolInfo_array(declVar);
    }
    
    public static FuncVariableTable getGlobalFuncTable() {
    	return globalContext.globalFuncTables;
    }
    
    public static SymbolTable getGlobalSymbolTables() {
    	return globalContext.globalSymbolTables;
    }
    
    public static void addClass(String className) {
    	// 记录有什么类
    	globalContext.classList.add(className);
    }
    
    public static ArrayList<String> getClassList() {
    	// 把已经定义的类列出来
    	return globalContext.classList;
    }
    
    public static String getFuncType(String funcName) {
    	// 根据函数名获取返回类型
    	String nowClass = globalContext.nowClassField;
    	if (nowClass != null) return globalContext.funcTypeMap.get(nowClass + "." + funcName);
    	else return globalContext.funcTypeMap.get(funcName);
    }
    
    public static FuncVariableTable getFuncVarDeclList(String funcvarName) {
    	return globalContext.funcTables.get(funcvarName);
    }
    
    public static void addClassAttrAssign(String classname, ArrayList<AstItem> assign) {
    	globalContext.class2attrAssign.put(classname, assign);
    }
    
    public static ArrayList<AstItem> getClassAttrAssign(String classname) {
    	return globalContext.class2attrAssign.get(classname);
    }
    
    public static boolean isDefinedFunction(String name) {
//    	System.out.println(globalContext.funcTypeMap.keySet());
//    	System.out.println(name);
//    	System.out.println(globalContext.funcTypeMap.containsKey(name));
    	return globalContext.funcTypeMap.containsKey(name);
    }
    
    public static boolean isNoReload(String funcname) {
    	return (globalContext.funcReload.containsKey(funcname)) && (globalContext.funcReload.get(funcname).size() == 1);
    }
    
    public static String toDebugString() {
    	String resultString = "";
    	// 现存的类
    	resultString += "##############################\n";
    	resultString += "Existing Class is as Follow : ";
    	for (String className : globalContext.classList) {
    		resultString += className + ", ";
    	}
    	resultString += "\n";
    	
    	// 现存的函数
    	resultString += "##############################\n";
    	resultString += "Existing Functions is as Follow : \n\n";
    	for (String key : globalContext.funcTypeMap.keySet()) {
    		resultString += key + "->" + globalContext.funcTypeMap.get(key) + ", ";
    	}
    	resultString += "\n";
    	
    	// 符号表
    	resultString += "##############################\n";
    	resultString += "Symbol Tables is as Follow : \n\n";
    	resultString += "GLOBAL : \n";
    	resultString += globalContext.globalSymbolTables.toString() + "\n";
		for (String key : globalContext.symbolTables.keySet()) {
			resultString += key + " : \n" + globalContext.symbolTables.get(key).toString() + "\n";
		}
		
		// 函数变量调用表
    	resultString += "##############################\n";
    	resultString += "FuncVarible Tables is as Follow : \n\n";
    	resultString += "GLOBAL : \n";
    	resultString += globalContext.globalFuncTables.toString() + "\n";
		for (String key : globalContext.funcTables.keySet()) {
			resultString += key + " : \n" + globalContext.funcTables.get(key).toString() + "\n";
		}
		
		// 函数重载表
    	resultString += "##############################\n";
    	resultString += "Func Reloads Tables is as Follow : \n\n";
		for (String key : globalContext.funcReload.keySet()) {
			resultString += key + " : [";
			for (FuncParamsTypeList l : globalContext.funcReload.get(key)) {
				resultString += l.toString() + ", ";
			}
			resultString += "]";
			resultString += "\n";
		}
    	return resultString;
    }
}
